﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Loggerz.Interfaces.Repository;
using Loggerz.Classes.LogClass;
using Loggerz.Enumerations;
using Loggerz.Interfaces.User;
using CommonLibrary.Interfaces.Emailer;

namespace Loggerz.Repositories.LogRepository
{
    public class LogRepositoryBase : ILogRepositoryBase<LogBase>
    {
        private List<LogBase> _errorList;
        private LogBase _currentError;
        private Level _errorLevel;
        private IUserBase _user;
        private bool _overrideErrorLevel;
        private IEmailer _emailOutput;

        public List<LogBase> ErrorList
        {
            get
            {
                return _errorList;
            }
            set
            {
                _errorList = value;
            }
        }

        public LogBase CurrentError
        {
            get
            {
                return _currentError;
            }
            set
            {
                _currentError = value;
            }
        }

        public Level ErrorLevel
        {
            get
            {
                return _errorLevel;
            }
            set
            {
                _errorLevel = value;
            }
        }

        public IUserBase CurrentUser
        {
            get
            {
                return _user;
            }
            set
            {
                _user = value;
            }
        }

        public IEmailer Emailer
        {
            get
            {
                return _emailOutput;
            }
            set
            {
                _emailOutput = value;
            }
        }

        public bool OverrideErrorLevel
        {
            get
            {
                return _overrideErrorLevel;
            }
            set
            {
                _overrideErrorLevel = value;
            }
        }

        public bool AddError(LogBase errorObject)
        {
            bool valid = false;
            try
            {
                //check if the error object has a valid user item
                //if not then assign it the repository user 
                if (errorObject.User == null)
                {
                    errorObject.User = _user.Clone();
                }

                //check to see if we should override the error level 
                //this really should only be user to log everything as critical
                if (_overrideErrorLevel)
                {
                    errorObject.ErrorLevel = _errorLevel;
                }

                //check to see if the error list has any items. 
                //this is so we can set the correct sequence number. 
                if (errorObject.SequenceNumber == 0)
                {
                    //get the max sequence number from the list.
                    errorObject.SequenceNumber = GetNextSequenceNumber();
                }


                //add the item to the error list. 
                _errorList.Add(errorObject);

                //set the current error to this item.
                _currentError = errorObject;
                valid = true;
            }
            catch (Exception error)
            {
                AddError(new LogBase(error, GetNextSequenceNumber(), Level.Critical, this.GetType().Name, "AddError", null, Guid.NewGuid()));

            }
            return valid;
        }

        public bool ClearErrors()
        {
            bool valid = false;
            //resetting error stack.
            try
            {
                _errorList = new List<LogBase>();
                _currentError = null;
                valid = true;
            }
            catch (Exception error)
            {
                AddError(new LogBase(error, GetNextSequenceNumber(), Level.Critical, this.GetType().Name, "ClearErrors", null, Guid.NewGuid()));
            }

            return valid;
        }

        public bool HasErrors()
        {
            bool valid = false;
            try
            {
                if (_errorList != null && _errorList.Count > 0)
                {
                    valid = true;
                }
                else
                {
                    if (_errorList == null)
                    {
                        throw new NotImplementedException("Error List is missing. ");
                    }
                }
            }
            catch (Exception error)
            {
                AddError(new LogBase(error, GetNextSequenceNumber(), Level.Critical, this.GetType().Name, "HasErrors", null, Guid.NewGuid()));

            }

            return valid;
        }

        public int GetNextSequenceNumber()
        {
            int sequenceNumber = 0;
            try
            {
                if (_errorList != null && _errorList.Count > 0)
                {
                    sequenceNumber = _errorList.Max(errorItem => errorItem.SequenceNumber);
                }
                else
                {
                    if (_errorList != null && _errorList.Count == 0)
                    {
                        sequenceNumber = 1;
                    }
                    else
                    {
                        throw new NotImplementedException("Error List is Missing.");
                    }
                }
            }
            catch (Exception error)
            {
                AddError(new LogBase(error, GetNextSequenceNumber(), Level.Critical, this.GetType().Name, "GetNextSequenceNumber", null, Guid.NewGuid()));
            }

            return sequenceNumber;
        }

        public LogRepositoryBase(IUserBase user, Level errorLevel = Level.Critical, bool overRideErrorLevel = false, IEmailer emailObject = null)
        {
            try
            {
                _errorList = new List<LogBase>();
                _user = user;
                _errorLevel = errorLevel;
                _overrideErrorLevel = overRideErrorLevel;
                _emailOutput = emailObject;
            }
            catch (Exception error)
            {
                throw new ArgumentNullException("Invalid User object passed in", error);
            }
        }




       

        public bool EmailErrors()
        {
            bool valid = false;
            try
            {
                if (_emailOutput != null)
                {

                }
                else
                {
                    throw new InvalidOperationException("Email Output Object does not exit");
                }
            }
            catch (Exception error)
            {
                AddError(new LogBase(error,GetNextSequenceNumber(),Level.Critical,this.GetType().Name,"EmailErrors",null,Guid.NewGuid()));
            }


            return valid;
        }
    }
}
